package com.hsource.doctorcenter.service.doctor.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.hsource.common.utils.bean.BeanUtils;
import com.hsource.doctorcenter.conf.dataSource.aspect.SnowflakeIdWorker;
import com.hsource.doctorcenter.domain.doctor.Doctor;
import com.hsource.doctorcenter.domain.doctor.DoctorApi;
import com.hsource.doctorcenter.domain.doctor.DoctorPhoneInfo;
import com.hsource.doctorcenter.domain.doctor.DoctorPrice;
import com.hsource.doctorcenter.manager.AsyncManager;
import com.hsource.doctorcenter.manager.factory.AsyncFactory;
import com.hsource.doctorcenter.mapper.DoctorMapper;
import com.hsource.doctorcenter.mapper.DoctorPriceMapper;
import com.hsource.doctorcenter.service.api.IApiService;
import com.hsource.doctorcenter.service.doctor.IDoctorService;
import com.hsource.doctorcenter.util.PriceProcessingUtil;
import com.hsource.doctorcenter.util.RedisKeyUtil;
import com.hsource.doctorcenter.util.RedisUtil;
import com.hsource.doctorcenter.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yangYang
 * @version 1.0
 * @date 2020/9/23 15:17
 * @describe 医生信息Service业务层处理
 */
@Service
public class DoctorServiceImpl implements IDoctorService {
    @Autowired
    private DoctorMapper doctorMapper;
    @Autowired
    private DoctorPriceMapper doctorPriceMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IApiService apiService;

    /**
     * 查询医生信息
     *
     * @param id 医生信息ID
     * @return 医生信息
     */
    @Override
    public Doctor selectDoctorById(String id) {
        return doctorMapper.selectDoctorById(id);
    }

    /**
     * 查询医生信息列表
     *
     * @param doctor 医生信息
     * @return 医生信息
     */
    @Override
    public List<Doctor> selectDoctorList(Doctor doctor) {
        return doctorMapper.selectDoctorList(doctor);
    }

    /**
     * 新增医生信息
     *
     * @param doctor 医生信息
     * @return 结果
     */
    @Override
    public int insertDoctor(Doctor doctor) {
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);
        long l = idWorker.nextId();
        doctor.setId(String.valueOf(l));
        return doctorMapper.insertDoctor(doctor);
    }

    /**
     * 修改医生信息
     *
     * @param doctor 医生信息
     * @return 结果
     */
    @Override
    public int updateDoctor(Doctor doctor) {
        return doctorMapper.updateDoctor(doctor);
    }

    /**
     * 根据doctor_id 查询医生信息
     * @param doctor_id
     * @return
     */
    @Override
    public Doctor selectDoctorByDoctorId(String doctor_id){
        return doctorMapper.selectDoctorByDoctorId(doctor_id);
    }
    /**
     * 删除医生信息对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteDoctorByIds(String ids) {
        return doctorMapper.deleteDoctorByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除医生信息信息
     *
     * @param id 医生信息ID
     * @return 结果
     */
    @Override
    public int deleteDoctorById(String id) {
        return doctorMapper.deleteDoctorById(id);
    }

    /**
     * 根据医生id数组查询医生集合信息
     * @param doctorIds 医生ids
     * @return
     */
    @Override
    public List<DoctorApi> selectDoctorListByDoctorIds(String doctorIds){
        return doctorMapper.selectDoctorListByDoctorIds(Convert.toStrArray(doctorIds));
    }

    /**
     * 获取医生详情
     * @param userId 用户id
     * @param doctorId 医生id
     * @return
     * @throws ParseException
     * @throws NoSuchAlgorithmException
     */
    @Override
    public Doctor getDoctorsDetailed(String userId, String doctorId) throws ParseException, NoSuchAlgorithmException {
        String key = RedisKeyUtil.getRedisKeyString("",RedisKeyUtil.DOCTORLIST);
        DoctorPrice doctorPrice=new DoctorPrice();
        doctorPrice.setDoctorId(doctorId);
        doctorPrice.setConsultType("TH");
        List<DoctorPrice> doctorPrices = doctorPriceMapper.selectDoctorPriceList(doctorPrice);
        long telPrice=0;
        if(doctorPrices.stream().count()>0){
            doctorPrices=doctorPrices.stream().filter(d->d.getPrice()>0).collect(Collectors.toList());
            doctorPrices.sort((a,b)->a.getPrice().intValue()-b.getPrice().intValue());
            telPrice=doctorPrices.get(0).getPrice();
        }
        Doctor doctor=null;
        if(redisUtil.hHasKey(key, doctorId)){
            Object object = redisUtil.hget(key,doctorId);
            doctor = JSONObject.parseObject(JSONObject.toJSONString(object), Doctor.class);
        }else{
            Doctor selDoctor=new Doctor();
            selDoctor.setDoctor_id(doctorId);
            List<Doctor> collect = doctorMapper.selectDoctorList(selDoctor).stream().collect(Collectors.toList());
            if(collect.stream().count()>0){
                doctor = collect.stream().findFirst().get();
            }else{
                String doctorsDetailed = apiService.getDoctorsDetailed(userId, doctorId);
                doctor = JSONObject.parseObject(doctorsDetailed, Doctor.class);
                doctor.setPrice(PriceProcessingUtil.priceFloat(doctor.getPrice()));

            }
        }
        if (StringUtils.isNotNull(doctor)) {
            doctor.setTel_price(String.valueOf(telPrice));
        }
        return doctor;
    }


    /**
     * 找医生接口
     * @param userId 用户id
     * @param famousDoctor 是否筛选名医
     * @param startNum 开始数
     * @param count 每次取的医生数
     * @param province 省份
     * @param city 城市
     * @param serviceType 服务类型
     * @param sortType 排序（空默认综合排序）类型   好评：goodRate 咨询数：replyNum  综合：synth
     * @return
     * @throws ParseException
     * @throws NoSuchAlgorithmException
     */
    @Override
    public Map<String, Object> getDoctorsList(String userId,int famousDoctor,int startNum,int count,String province,String city,String serviceType,String clinicNo,String sortType) throws ParseException, NoSuchAlgorithmException {
        String resultString = apiService.getDoctors(userId, famousDoctor, startNum, count, province, city, serviceType, clinicNo);
        return getDoctorMap(resultString,userId,sortType);
    }

    /**
     * 快捷电话回调快捷医生信息
     * @param bodyMap
     */
    public void close(Map<String,Object> bodyMap){
        if(bodyMap.containsKey("service_id")){
            //快捷电话

        }
        if(bodyMap.containsKey("problem_id")){
            //医生回复
        }
    }
    /**
     * 获取医生时长价格|可预约时间
     * @param userId 用户id
     * @param doctorId 医生id
     * @throws ParseException
     * @throws NoSuchAlgorithmException
     */
    @Override
    public Map<String,Object> getDoctorPhoneInfo(String userId ,String doctorId) throws ParseException, NoSuchAlgorithmException {
        String resultString = apiService.getDoctorPhoneInfo(doctorId, userId);
        JSONObject jsonObject = JSONObject.parseObject(resultString);
        Map<String,Object> map=new HashMap<>();
        map.put("error",jsonObject.getString("error"));
        map.put("error_msg",jsonObject.getString("error_msg"));
        List<DoctorPhoneInfo> doctorPhoneInfos=new ArrayList<>();
        if(jsonObject.getString("error").equals("0")){
            String telPrice = jsonObject.get("price_info").toString();
            if(StringUtils.isNotBlank(telPrice)) {
                AsyncManager.me().execute(AsyncFactory.consolidatedataDoctorPriceByPhone(jsonObject,doctorId));
                JSONObject.parseObject(telPrice, Map.class).forEach((k,v)->{
                    DoctorPhoneInfo doctorPhoneInfo=new DoctorPhoneInfo();
                    doctorPhoneInfo.setDuration(k.toString());
                    doctorPhoneInfo.setDurationPrice(PriceProcessingUtil.priceFloatYuan(((BigDecimal)v).longValue()));
                    doctorPhoneInfos.add(doctorPhoneInfo);
                });
                map.put("telPriceArray",doctorPhoneInfos);
                map.put("reservation",jsonObject.get("recent_subscribable_time"));
            }
        }
        return map;
    }
    /**
     * 推荐医生
     * @param userId 用户id
     * @param ask 首次
     * @return
     * @throws ParseException
     * @throws NoSuchAlgorithmException
     */
    @Override
    public Map<String, Object> recommendedDoctors(String userId,String ask) throws ParseException, NoSuchAlgorithmException {
        String resultString = apiService.recommendedDoctors(userId, ask);
        return getDoctorMap(resultString,userId,"");
    }
    /**
     * 医生列表数据查询逻辑处理
     * @param resultString 接口返回医生列表数据
     * @param userId 用户id
     * @param sortType 排序（空默认综合排序）类型   好评：goodRate 咨询数：replyNum  综合：synth
     * @return
     */
    public Map<String,Object> getDoctorMap(String resultString,String userId,String sortType){
        JSONObject jsonObject = JSONObject.parseObject(resultString);

        Map<String, Object> doctorsMap = new HashMap<>();
        doctorsMap.put("doctors", new JSONArray());
        doctorsMap.put("error", jsonObject.get("error"));
        doctorsMap.put("error_msg", jsonObject.get("error_msg"));
        if(jsonObject.get("error").toString().equals("0")) {
            JSONArray jsonArray = JSONObject.parseArray(jsonObject.get("doctors").toString());
            if(jsonArray.stream().count()>0){
                //异步同步医生数据
                AsyncManager.me().execute(AsyncFactory.syncDoctorsByReids(jsonArray,userId));
                AsyncManager.me().execute(AsyncFactory.syncDoctors(jsonArray,userId));

                List<Doctor> doctors = JSONObject.parseArray(jsonArray.toString(), Doctor.class);
                List<DoctorApi> doctorApis=new ArrayList<>();
                doctors.stream().forEach(d->{
                    String doctor_id=d.getId();
                    DoctorApi doctorApi = new DoctorApi();

                    //redis 缓存
                    String key = RedisKeyUtil.getRedisKeyString("",RedisKeyUtil.DOCTORLIST);
                    boolean b = redisUtil.hHasKey(key,doctor_id);
                    if(b){
                        Object object = redisUtil.hget(key,doctor_id);
                        doctorApi= JSONObject.parseObject(JSONObject.toJSONString(object),DoctorApi.class);
                    }else{
                        //api 拉取信息
                        try {
                            Doctor doctor = getDoctorsDetailed(userId,doctor_id);
                            BeanUtils.copyBeanProp(doctorApi,doctor);
                            if(StringUtils.isNotNull(doctor.getTags())) {
                                doctorApi.setTag(Joiner.on(",").join(doctor.getTags()));
                            }
                            doctorApi.setIs_famous(doctor.isIs_famous_doctor() ? 0 : 1);
                            doctorApi.setPurchase_num(d.getPurchase_num());
                            doctorApi.setDoctor_id(doctor_id);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        } catch (NoSuchAlgorithmException e) {
                            e.printStackTrace();
                        }
                    }
                    doctorApis.add(doctorApi);
                });

                //根据排序类型对医生集合排序
                sortDoctors(doctorApis,sortType);
                doctorsMap.put("doctors",doctorApis);
            }
            return doctorsMap;
        }else{
            return doctorsMap;
        }
    }

    /**
     * 医生集合排序
     * @param doctorApis 医生集合
     * @param sortType 排序类型
     * @return
     */
    public List<DoctorApi> sortDoctors(List<DoctorApi> doctorApis,String sortType){
        if(doctorApis.stream().count()>0){
            if(StringUtils.isBlank(sortType)){
//                doctorApis.sort((a,b)->b.getSolution_score()-a.getSolution_score());
            }else{
                if(sortType.equals("synth")){
                    doctorApis.sort((a,b)->b.getSolution_score()-a.getSolution_score());
                }
                if(sortType.equals("replyNum")){
                    doctorApis.sort((a,b)->b.getReply_num()-a.getReply_num());
                }
                if(sortType.equals("goodRate")){
                    doctorApis.sort((a,b)->b.getGood_at().compareTo(a.getGood_at()));
                }
            }

        }
        return doctorApis;
    }

    /**
     * 查找当前最小价格
     * @param tel_price
     * @param price
     * @return
     */
    public static long minPrice(String tel_price,long price){
        long[] showPrice = {price};
        if(StringUtils.isNotBlank(tel_price)) {
            Map<String, Integer> map = JSONObject.parseObject(tel_price, Map.class);
            map.forEach((k, v) -> {
                if (PriceProcessingUtil.priceFloat(v.longValue()) < price) {
                    showPrice[0] = PriceProcessingUtil.priceFloat(v.longValue());
                }
            });
        }
        return showPrice[0];
    }

    /**
     * 搜索医生接口
     * @param queryText 搜索词
     * @param page 页码 1-10
     * @param province 省份
     * @param city 城市
     * @return
     */
    @Override
    public Map<String,Object> searchDoctors(String userId,String queryText,int page,String province,String city) throws ParseException, NoSuchAlgorithmException {
        String resultString = apiService.searchDoctors(userId, queryText,page,province,city);
        return getDoctorMap(resultString,userId,"");
    }
}
